﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace Gem
{
    /// <summary>
    /// Manages the environmnet definitions.
    /// </summary>
    public class GeDefinitionsManager
    {
        private readonly Dictionary<string, EnvironmentDefinition> m_environments;
 
        /// <summary>
        /// Creates a new instance of <see cref="GeDefinitionsManager"/>.
        /// </summary>
        public GeDefinitionsManager()
        {
            m_environments = new Dictionary<string, EnvironmentDefinition>();

            IsPopulating = false;
        }

        /// <summary>
        /// Gets the enumeration of the managed environments.
        /// </summary>
        public IEnumerable<EnvironmentDefinition> Environments
        {
            get
            {
                return m_environments.Values;
            }
        }

        /// <summary>
        /// Gets the count of environments identified and available.
        /// </summary>
        public int EnvironmentsCount
        {
            get
            {
                return m_environments.Count;
            }
        }

        /// <summary>
        /// Gets whether the environments' information is now being populated.
        /// </summary>
        public bool IsPopulating { get; private set; }

        /// <summary>
        /// Remove a specific environment from the managed collection.
        /// </summary>
        /// <param name="folderName"></param>
        public void RemoveEnvironment(string folderName)
        {
            if (m_environments.ContainsKey(folderName))
            {
                m_environments.Remove(folderName);
            }
        }

        /// <summary>
        /// Recursively searches for folders hosting SCC and add them to the collection of environments.
        /// This operation clears the environments' collection and starts over.
        /// This operation is NOT thread-safe.
        /// </summary>
        /// <param name="rootFolder">The root folder where to start searching.</param>
        /// <param name="maxDepth">The maximum depth to search.</param>
        public void PopulateEnvironments(string rootFolder, int maxDepth)
        {
            if (!Directory.Exists(rootFolder))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Folder '{0}' does not exist.", rootFolder));
            }

            IsPopulating = true;

            m_environments.Clear();

            PopulateEnvironmentEx(rootFolder, maxDepth, 0);
            
            IsPopulating = false;
        }

        private void PopulateEnvironmentEx(string rootFolder, int maxDepth, int depth)
        {
            foreach (var folder in Directory.EnumerateDirectories(rootFolder))
            {
                var sccProvider = SccProvidersStaticUtils.Instance.GetProvider(folder);

                if (sccProvider != null)
                {
                    m_environments.Add(folder, new EnvironmentDefinition(sccProvider));
                }
                else
                {
                    if (depth < maxDepth)
                    {
                        PopulateEnvironmentEx(folder, maxDepth, depth + 1);
                    }
                }
            }
        }
    }
}
